import hudson.FilePath
import hudson.model.Node
import hudson.model.Slave
import jenkins.model.Jenkins
import groovy.time.*

def createVersion(BUILD_NUMBER)
{
   return new Date().format('yyMM') + " ${BUILD_NUMBER} "
}

def allOnlineNodes()
{
    def nodes = []
    Jenkins.instance.computers.each
	{
		if(it.isOnline())
		{
			nodes << it.getDisplayName()
		}
    }
    return nodes
}


def findNodes()
{
   Jenkins jenkins = Jenkins.instance
   def jenkinsNodes =jenkins.nodes
   // while(1)
   {
      for (Node node in jenkinsNodes) 
      {
         // sleep(1000)
         // Make sure slave is online
         if (!node.getComputer().isOffline()) 
         {           
               //Make sure that the slave busy executor number is 0.
               if(node.getComputer().countBusy()==0)
               {
                  println "'$node.nodeName' can take jobs !!!"
                  return 0
               }
               else
               {
                  println "$node.nodeName' is busy !!!"
               }
         }
         else
         {
               println "'$node.nodeName' is offline !!!" 
         }
      }
      // sleep(1000)
   }
}


def getAllJobs()
{
   for (Project job : Hudson.getInstance().getProjects())
   {
      echo "${job.getName()}"
   }
}

// 返回任意空闲的Node
def getAnyIdleNode()
{
   def nodes = []
   Jenkins.instance.computers.each
   {
      if(it.isOnline())
      {
         if(it.isPartiallyIdle())
         {
            nodes << it.getDisplayName()
         }
      }
   }

   if(nodes.size() == 0)
      return null
   else
      return nodes[0]
}

// 所有空闲节点
def allIdleNodes()
{
   def nodes = []
   Jenkins.instance.computers.each
   {
      if(it.isOnline())
      {
         if(it.isPartiallyIdle())
         {
            nodes << it.getDisplayName()
         }
      }
   }
   return nodes
}

def allExecutors()
{
   def executors = []
   for(int i = 0; i < Jenkins.instance.computers.size(); i++)
   {
      def computer = Jenkins.instance.computers[i]
      if(computer.isOnline())
      {
         for(int j = 0; j < computer.executors.size(); j++)
         {
            executors.add(computer.executors[j].getDisplayName()) 
         }
      }
   }
   println executors
   return executors
}

def slaveInfo()
{
   for (aSlave in hudson.model.Hudson.instance.slaves)
   {
      println('====================');
      println('Name: ' + aSlave.name);
      println('getLabelString: ' + aSlave.getLabelString());
      println('getNumExectutors: ' + aSlave.getNumExecutors());
      println('getRemoteFS: ' + aSlave.getRemoteFS());
      println('getMode: ' + aSlave.getMode());
      println('getRootPath: ' + aSlave.getRootPath());
      println('getDescriptor: ' + aSlave.getDescriptor());
      println('getComputer: ' + aSlave.getComputer());
      println('\tcomputer.isAcceptingTasks: ' + aSlave.getComputer().isAcceptingTasks());
      println('\tcomputer.isLaunchSupported: ' + aSlave.getComputer().isLaunchSupported());
      println('\tcomputer.getConnectTime: ' + aSlave.getComputer().getConnectTime());
      println('\tcomputer.getDemandStartMilliseconds: ' + aSlave.getComputer().getDemandStartMilliseconds());
      println('\tcomputer.isOffline: ' + aSlave.getComputer().isOffline());
      println('\tcomputer.countBusy: ' + aSlave.getComputer().countBusy());
      //if (aSlave.name == 'NAME OF NODE TO DELETE') {
      //  println('Shutting down node!!!!');
      //  aSlave.getComputer().setTemporarilyOffline(true,null);
      //  aSlave.getComputer().doDoDelete();
      //}
      println('\tcomputer.getLog: ' + aSlave.getComputer().getLog());
      println('\tcomputer.getBuilds: ' + aSlave.getComputer().getBuilds());
   }
}

def lockFileName(String projectName, String nodeName)
{
   return config.projectDir(projectName) + "/" + config.distributeDir() + "/" + nodeName + ".lock"
}

def createLockFile(String projectName, String nodeName)
{
   String fileName = lockFileName(projectName, nodeName)
   file = new File(fileName)
   file.createNewFile()
}

def isLockFileExist(String projectName, String nodeName)
{
   String fileName = lockFileName(projectName, nodeName)
   file = new File(fileName)
   return file.exists()
}

def deleteLockFile(String projectName, String nodeName)
{
   String fileName = lockFileName(projectName, nodeName)
   file = new File(fileName)
   file.delete()
}

def deleteAllLockFiles(String projectName)
{
   def nodeNames = allOnlineNodes()
   for(int nodeIndex = 0; nodeIndex < nodeNames.size(); nodeIndex++)
   {
      deleteLockFile(projectName, nodeNames[nodeIndex])
   }
}

def distributeTask(String projectName, String jobName, int workCount, int paramsWorkesPerNode)
{
   def allNodes = allOnlineNodes()
   def workesPerNode = config.workesPerNode(workCount, allNodes.size(), paramsWorkesPerNode)

   def isFirstTime = [:]
   for(int nodeIndex = 0; nodeIndex < allNodes.size(); nodeIndex++)
   {
      isFirstTime.put(allNodes[nodeIndex], true)
   }

   // 分发任务
   for(int workIndex = 0; workIndex < workCount;)
   {
      // 任务太多时，每次分发node的idle状态不一样，因此每次分发时，重新拿idle的nodes，
      def nodeNames = allIdleNodes()
      for(int nodeIndex = 0; nodeIndex < nodeNames.size(); nodeIndex++)
      {
         if(workIndex >= workCount)
            break;
         def nodeName = nodeNames[nodeIndex]

         // 正在编译任务
         if(isLockFileExist(projectName, nodeName))
         {
            continue;
         }
         else
         {
            createLockFile(projectName, nodeName)

            int endWorkIndex = workIndex + workesPerNode
            def nodeIsFirstTime = isFirstTime[nodeName]

            build job: jobName, parameters: [
               string(name: 'START_WORK_INDEX', value: "${workIndex}"),
               string(name: 'END_WORK_INDEX', value: "${endWorkIndex}"),
               string(name: 'EXECUTE_NODE', value: "${nodeName}"),
               string(name: "PROJECT", value: projectName),
               booleanParam(name: "FIRST_TIME", value: nodeIsFirstTime)
               ], quietPeriod: 0, wait: false, propagate: true
            
            workIndex += workesPerNode

            isFirstTime[nodeName] = false
         }
      }
      // 每0.1秒分发一次任务
      Thread.sleep(100)
   }
}

return this